from django.db import models
from rest_framework.exceptions import ValidationError

from user.models import ProjUser, ProjUserGroup


class Question(models.Model):
    QUESTION_TYPES = (
        ('CQ', 'Choice Question'),
        ('FBQ', 'Fill in the Blank Question'),
    )

    # 必填，题目的创建者
    creator = models.ForeignKey(ProjUser, on_delete=models.CASCADE, blank=True)

    # 必填，题目的类型，CQ选择，FBQ填空
    type = models.CharField(max_length=4, choices=QUESTION_TYPES, verbose_name='类型')
    # 必填，题目的权限，0公开，1不公开
    authority = models.PositiveIntegerField(verbose_name='权限', default=0)
    # 必填，题干
    stem = models.TextField(verbose_name='题干', db_index=True)
    # 选填，题目名称
    name = models.CharField(max_length=10, blank=True, null=True, verbose_name='题名', db_index=True)
    # 必填，标签
    label = models.CharField(max_length=10, verbose_name='标签', db_index=True)
    # 选填，解答
    analysis = models.TextField(verbose_name='解析', blank=True, null=True, default='')
    # 不填
    is_banned = models.BooleanField(default=False, verbose_name='是否被封禁')
    # 必填
    create_time = models.DateTimeField(verbose_name='题目创建时间', blank=True)
    # 必填
    update_time = models.DateTimeField(verbose_name='题目更新时间', blank=True)

    def clean(self):
        if self.type == 'CQ':
            if hasattr(self, 'blank'):
                raise ValidationError("Choice question cannot have blank field.")
        elif self.type == 'FBQ':
            if hasattr(self, 'choice'):
                raise ValidationError("Fill in the blank question cannot have choice field.")

    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

    class Meta:
        verbose_name_plural = '题目'


class Choice(models.Model):
    # 必填，链接题目
    question = models.OneToOneField(Question, on_delete=models.CASCADE,
                                    blank=True, null=True, related_name='choice')

    # 必填，题目类型，0单选，1多选，2不定项
    type = models.PositiveIntegerField(verbose_name='类型')
    # 必填，选项数
    options_cnt = models.PositiveIntegerField(verbose_name='选项数')
    # 必填，选项json {"A":"aaa","B":"xxx"}
    options = models.TextField(verbose_name='选项')
    # 必填，答案数
    ans_cnt = models.PositiveIntegerField(verbose_name='答案数')
    # 必填，答案json ["A", "B"]
    ans = models.TextField(verbose_name='答案')


class Blank(models.Model):
    # 必填，链接题目
    question = models.OneToOneField(Question, on_delete=models.CASCADE,
                                    blank=True, null=True, related_name='blank')

    # 必填，待填空数目
    blank_cnt = models.PositiveIntegerField(verbose_name='填空数')
    # 必填，答案json {"1":["aa","bb"], "2":["cc","dd"]}
    ans = models.TextField(verbose_name='答案')


class QuestionGroup(models.Model):
    """
    detail权限校验顺序：
    1.先看是否是公开题组
    2.再看creator和请求用户是否相同
    3.最后看是否有组共享关系
    若满足上述任意一条则有权访问该问题组的detail信息，反之则无法查看
    """
    # 题组里的题目，题号组成的json数组，可以无元素，但是该字段一定得有
    questions = models.ManyToManyField(Question, related_name='question_group', blank=True)
    # 必填，题组创建者
    creator = models.ForeignKey(ProjUser, on_delete=models.CASCADE, blank=True)
    # 选填，所属用户组
    user_groups = models.ManyToManyField(ProjUserGroup, related_name='question_groups', blank=True)

    # 问题可见性，必须设置，决定着是否能从全局搜索中检索到,0公开,1私有
    authority = models.PositiveIntegerField(verbose_name='权限', default=0)
    # 题组名，必须设置
    name = models.CharField(max_length=20, verbose_name='题组名称')
    # 选填，题组描述
    describe = models.TextField(verbose_name='问题组描述', blank=True, null=True)
    # 不填，题组是否被封禁
    is_banned = models.BooleanField(default=False, verbose_name='是否被封禁')
    # 必填，题组创建时间
    create_time = models.DateTimeField(verbose_name='题组创建时间', blank=True)

    class Meta:
        verbose_name_plural = '题目组'


class UserExerciseLog(models.Model):
    """
    字段：id,user外键,题目外键,错误时间
    """
    submit_user = models.ForeignKey(ProjUser, verbose_name='提交用户', on_delete=models.CASCADE
                                    , related_name='submit_logs')
    submit_question = models.ForeignKey(Question, verbose_name='提交题目', on_delete=models.CASCADE
                                        , related_name='submit_logs')
    submit_time = models.DateTimeField('提交时间')
    is_correct = models.BooleanField('正误情况')
    wrong_ans = models.TextField('错误答案', null=True)

    class Meta:
        verbose_name = '提交记录'
        verbose_name_plural = '题目提交记录'
